Self-hosted CVE monitoring for your stack. Watches a list of packages and pings your Slack channel the moment a new CVE drops for any of them.
Dependabot covers your repo dependencies. StackWatch covers everything else — your editor, your OS packages, your database, your identity provider, your terminal tools.
1. Create stack.yml in your repo:
notifications:
slack:
webhook_url: "${STACKWATCH_SLACK_WEBHOOK}"
packages:
- name: rails
ecosystem: RubyGems
tier: critical
- name: django
ecosystem: PyPI
tier: standard2. Add the workflow (copy examples/github-actions.yml to .github/workflows/cve-monitor.yml).
3. Add your Slack webhook as a repo secret named STACKWATCH_SLACK_WEBHOOK.
That's it. New CVEs appear in your Slack channel within hours of disclosure.
# Create your stack config
docker run --rm ghcr.io/yourorg/stackwatch:latest init > stack.yml
# Edit stack.yml
# Run manually
docker run --rm \
-v $PWD/data:/data \
-v $PWD/stack.yml:/app/stack.yml:ro \
-e STACKWATCH_SLACK_WEBHOOK=https://hooks.slack.com/... \
ghcr.io/yourorg/stackwatch:latest run
# Set up cron (see examples/crontab)# Bitbucket Pipelines example
- step:
name: CVE Monitor
script:
- docker run --rm
-v $BITBUCKET_CLONE_DIR:/work
-e STACKWATCH_SLACK_WEBHOOK=$STACKWATCH_SLACK_WEBHOOK
ghcr.io/yourorg/stackwatch:latest run --config /work/stack.yml --state-path /work/state.jsongem install stackwatch
stackwatch init # generate stack.yml
stackwatch run # run oncestate_path: ./state.json # where to store seen CVE IDs
notifications:
slack:
webhook_url: "${STACKWATCH_SLACK_WEBHOOK}" # or set env var directly
packages:
- name: django
ecosystem: PyPI
tier: critical # critical | standard
- name: next
ecosystem: npm
tier: standardTiers:
critical— posts with@herementionstandard— silent post, no mention
Supported ecosystems: any ecosystem supported by osv.dev — PyPI, npm, RubyGems, Go, Maven, Debian, Alpine, NuGet, Hex, crates.io, and more.
@here :rotating_light: New CVE for django (PyPI)
CVE-2024-27351 — CVSS 7.5
Potential regular expression denial of service vulnerability in Django
Affected: >=3.2.0 Patched: 3.2.25
View on osv.dev
stackwatch run [--config stack.yml] [--state-path state.json]
stackwatch init [--force]
Environment variables:
| Variable | Description |
|---|---|
STACKWATCH_SLACK_WEBHOOK |
Slack Incoming Webhook URL |
STACKWATCH_STATE_PATH |
Override path to state.json |
StackWatch persists seen CVE IDs to state.json so it only alerts on new findings. The file path is configurable.
GitHub Actions: use actions/cache (see examples/github-actions.yml).
Cron/VPS: a local file. Done.
Bitbucket/GitLab: commit back via bot user, or upload as pipeline artifact.
stack.yml → Config → OSV querybatch → diff → Slack notify → state.json
- No database. State is a JSON file.
- One HTTP round-trip to osv.dev for all packages (uses
/v1/querybatch). - Pluggable notifiers — v1 ships Slack. Discord/webhook coming in v1.1.
- Pluggable sources — v1 ships osv.dev. RSS feeds and GitHub Advisory DB coming in v1.1.
See CONTRIBUTING.md. Issues and PRs welcome.
MIT — see LICENSE.